package com.lx.wrapper.every;


import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Pair;
import cn.hutool.core.util.ArrayUtil;
import com.lx.common.Wrappers;
import com.lx.constant.ano.FieldFunction;
import com.lx.constant.consts.CommonConstant;
import com.lx.constant.consts.SqlFormatConstant;
import com.lx.constant.consts.SqlKeyWordConstant;
import com.lx.constant.enums.*;
import com.lx.constant.execption.LambdaCheckException;
import com.lx.constant.execption.LambdaIllegalParamException;
import com.lx.constant.segment.Segment;
import com.lx.constant.segment.query.ColumnSegment;
import com.lx.constant.segment.query.GroupSegment;
import com.lx.constant.segment.query.OrderSegment;
import com.lx.constant.segment.query.join.JoinSegment;
import com.lx.inter.query.ResultConvertFunction;
import com.lx.inter.query.impl.DefaultResultConvertFunction;
import com.lx.wrapper.AbstractCommonConditionWrapper;
import com.lx.wrapper.AbstractEveryEntityLambdaConditionWrapper;
import com.lx.wrapper.AbstractWrapper;
import org.hibernate.query.Query;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;

/**
 * Lambda SQL Join语法操作
 * <p>
 * 注意
 * 1.必须指定Main实体关联类型!
 * 2.如未使用join相关方法,则本质与单表查询一致
 * 3.当前支持Join类型请参考:{@link GenericJoinTypeEnum}
 * 4.如关联多张表时,未指定【select】列,默认返回<MainEntity>的所有列数据
 * 5.此方法具备指定Join多个相同实体类型的能力,这通常在分区表下体现 <=> 分区表=(part_[num],part_[num]),此处需要将num设置在 {@link AbstractWrapper#setTableSuffix(String)}中,即能开启多个相同实体的Join（请注意:当前查询和其他条件暂不支持）
 *
 * @param <MainEntity> 任意主实体类型
 * @author lx
 * @create 2023/2/25 16:06
 **/
public class LambdaGenericJoinWrapper<MainEntity> extends AbstractEveryEntityLambdaConditionWrapper<MainEntity, LambdaGenericJoinWrapper<MainEntity>> implements ResultConvertFunction<LambdaGenericJoinWrapper<MainEntity>> {

    /**
     * 获取On条件类型Wrapper
     *
     * @return
     */
    public static LambdaOnConditionWrapper getOnConditionWrapper() {
        return new LambdaOnConditionWrapper();
    }

    /**
     * SQL查询结果转换代理类
     */
    protected final ResultConvertFunction<LambdaGenericJoinWrapper<MainEntity>> resultConvertProxy;

    public LambdaGenericJoinWrapper(Class<MainEntity> entityClass) {
        super(entityClass);
        if (entityClass == null) {
            throw new LambdaIllegalParamException("条件为任意实体类型拼接的JoinWrapper,必须指定主实体类型!");
        }
        resultConvertProxy = new DefaultResultConvertFunction(this);
    }

    @Override
    public LambdaGenericJoinWrapper<MainEntity> setEntityClass(Class<MainEntity> mainEntityClass) {
        if (mainEntityClass == null) {
            throw new LambdaIllegalParamException("条件为任意实体类型拼接的JoinWrapper,必须指定主实体类型!");
        }
        return super.setEntityClass(mainEntityClass);
    }

    @Override
    public LambdaGenericJoinWrapper<MainEntity> setConvertClass(Class<?> convertClass) {
        return this.resultConvertProxy.setConvertClass(convertClass);
    }

    @Override
    public Class<?> getConvertClass() {
        return this.resultConvertProxy.getConvertClass() == null ? checkAndGetValidEntityClass() : this.resultConvertProxy.getConvertClass();
    }

    /**
     * 设置/切换Having条件
     *
     * @return
     */
    public LambdaGenericJoinWrapper<MainEntity> having() {
        return super.setPreConditionType(PreConditionTypeEnum.HAVING);
    }

    public <OtherEntity> LambdaGenericJoinWrapper<MainEntity> groupBy(FieldFunction<OtherEntity, ?>... fnn) {
        if (fnn == null) {
            return this;
        }
        for (FieldFunction<OtherEntity, ?> fn : fnn) {
            groupBy(fn, null);
        }
        return this;
    }

    public <OtherEntity> LambdaGenericJoinWrapper<MainEntity> groupBy(FieldFunction<OtherEntity, ?> fn, SortWayEnum sortWay) {
        if (fn == null) {
            return this;
        }
        GroupSegment groupSegment = createAndAddSegment(new GroupSegment(), SegmentEnum.GROUP_BY, fn, null);
        groupSegment.setSortWay(sortWay == null ? SortWayEnum.ASC : sortWay);
        return this;
    }

    public <OtherEntity> LambdaGenericJoinWrapper<MainEntity> orderBy(FieldFunction<OtherEntity, ?>... fnn) {
        if (fnn == null) {
            return this;
        }
        for (FieldFunction<OtherEntity, ?> fn : fnn) {
            orderBy(fn, null);
        }
        return this;
    }

    public <OtherEntity> LambdaGenericJoinWrapper<MainEntity> orderBy(FieldFunction<OtherEntity, ?> fn, SortWayEnum sortWay) {
        if (fn == null) {
            return this;
        }
        OrderSegment orderSegment = createAndAddSegment(new OrderSegment(), SegmentEnum.ORDER_BY, fn, null);
        orderSegment.setSortWay(sortWay == null ? SortWayEnum.ASC : sortWay);
        return this;
    }

    /**
     * 构建多条不存在别名的查询列名
     *
     * @param fnn
     * @param <OtherEntity> 任意实体类型
     * @return
     */
    public <OtherEntity> LambdaGenericJoinWrapper<MainEntity> select(FieldFunction<OtherEntity, ?>... fnn) {
        if (fnn == null) {
            return this;
        }
        for (FieldFunction<OtherEntity, ?> fn : fnn) {
            select(fn, null);
        }
        return this;
    }

    /**
     * 构建单条存在别名的查询列名
     *
     * @param fnn
     * @param aliasName
     * @param <OtherEntity>
     * @return
     */
    public <OtherEntity> LambdaGenericJoinWrapper<MainEntity> select(FieldFunction<OtherEntity, ?> fnn, String aliasName) {
        if (fnn == null) {
            return this;
        }
        return addColumnSegment(aliasName, null, null, fnn);
    }

    /**
     * 构建多条存在别名的查询列名
     *
     * @param aliasColumns
     * @param <OtherEntity>
     * @return
     */
    public <OtherEntity> LambdaGenericJoinWrapper<MainEntity> select(Pair<FieldFunction<OtherEntity, ?>, String>... aliasColumns) {
        if (aliasColumns == null) {
            return this;
        }
        for (Pair<FieldFunction<OtherEntity, ?>, String> aliasColumn : aliasColumns) {
            select(aliasColumn.getKey(), aliasColumn.getValue());
        }
        return this;
    }

    /**
     * 构建单条子查询列的列名,建议设置别名
     *
     * @param childQueryWrapper
     * @param aliasName         列名别名
     * @return
     */
    public LambdaGenericJoinWrapper<MainEntity> selectChildQuery(AbstractCommonConditionWrapper childQueryWrapper, String aliasName) {
        if (childQueryWrapper == null) {
            return this;
        }
        return addColumnSegment(aliasName, childQueryWrapper, null);
    }

    public LambdaGenericJoinWrapper<MainEntity> selectChildQuery(Pair<AbstractCommonConditionWrapper, String>... aliasChildQueryWrappers) {
        if (aliasChildQueryWrappers == null) {
            return this;
        }
        for (Pair<AbstractCommonConditionWrapper, String> childWrapperPair : aliasChildQueryWrappers) {
            selectChildQuery(childWrapperPair.getKey(), childWrapperPair.getValue());
        }
        return this;
    }

    /**
     * 列名字段聚合函数 = 去重
     *
     * @param aliasName 聚合列别名
     * @param fnn
     * @return
     */
    public <OtherEntity> LambdaGenericJoinWrapper<MainEntity> distinct(String aliasName, FieldFunction<OtherEntity, ?>... fnn) {
        return addColumnSegment(aliasName, null, ColumnKeyWorldEnum.DISTINCT, fnn);
    }

    /**
     * 列名字段聚合函数 = 求和
     *
     * @param fnn
     * @return
     */
    public <OtherEntity> LambdaGenericJoinWrapper<MainEntity> sum(FieldFunction<OtherEntity, ?>... fnn) {
        return sum(null, fnn);
    }

    /**
     * 列名字段聚合函数 = 求和
     *
     * @param aliasName 聚合列别名
     * @param fnn
     * @return
     */
    public <OtherEntity> LambdaGenericJoinWrapper<MainEntity> sum(String aliasName, FieldFunction<OtherEntity, ?>... fnn) {
        return addColumnSegment(aliasName, null, ColumnKeyWorldEnum.SUM, fnn);
    }

    /**
     * 列名字段聚合函数 = 总数
     *
     * @param aliasName 聚合列别名
     * @param fnn
     * @return
     */
    public <OtherEntity> LambdaGenericJoinWrapper<MainEntity> count(String aliasName, FieldFunction<OtherEntity, ?>... fnn) {
        return addColumnSegment(aliasName, null, ColumnKeyWorldEnum.COUNT, fnn);
    }

    /**
     * 列名字段聚合函数 = 平均
     *
     * @param aliasName 聚合列别名
     * @param fnn
     * @return
     */
    public <OtherEntity> LambdaGenericJoinWrapper<MainEntity> avg(String aliasName, FieldFunction<OtherEntity, ?>... fnn) {
        return addColumnSegment(aliasName, null, ColumnKeyWorldEnum.AVG, fnn);
    }

    /**
     * 【主实体类型】与【任意实体类型】进行 (Left Join) 关联,同时可以指定【单个EQ】条件的方法
     * <p>
     * SQL示例:
     * select * from MainEntity m left join OtherEntity o on m.mainOnEqKey = o.otherOnEqKey
     *
     * @param otherEntityClass 任意实体类型
     * @param mainOnEqKey      主实体类型属性
     * @param otherOnEqKey     任意实体类型属性
     * @param <OtherEntity>    任意实体对象
     * @return
     */
    public <OtherEntity> LambdaGenericJoinWrapper<MainEntity> leftJoin(Class<OtherEntity> otherEntityClass, FieldFunction<MainEntity, ?> mainOnEqKey, FieldFunction<OtherEntity, ?> otherOnEqKey) {
        return leftJoin(getEntityClass(), otherEntityClass, mainOnEqKey, otherOnEqKey);
    }

    /**
     * 【任意实体类型】与【任意实体类型】进行 (Left Join) 关联,同时可以指定【单个EQ】条件的方法
     * <p>
     * SQL示例:
     * select * from OtherEntity1 o1 left join OtherEntity2 o2 on o1.o1OnEqKey = o2.o2OnEqKey
     *
     * @param o1Class
     * @param o2Class
     * @param o1OnEqKey
     * @param o2OnEqKey
     * @param <OtherEntity1> 任意实体类型
     * @param <OtherEntity2> 任意实体类型
     * @return
     */
    public <OtherEntity1, OtherEntity2> LambdaGenericJoinWrapper<MainEntity> leftJoin(Class<OtherEntity1> o1Class, Class<OtherEntity2> o2Class, FieldFunction<OtherEntity1, ?> o1OnEqKey, FieldFunction<OtherEntity2, ?> o2OnEqKey) {
        return leftJoin(o1Class, o2Class, new Pair<>(o1OnEqKey, o2OnEqKey));
    }

    /**
     * 【主实体类型】与【任意实体类型】进行 (Left Join) 关联,同时可以指定【多个EQ】条件的方法
     * <p>
     * SQL示例:
     * select * from MainEntity m left join OtherEntity o on m.ok1 = o.ok1  and  m.ok2 = o.ok2 ...
     *
     * @param otherEntityClass
     * @param onEqConditionPairs
     * @param <OtherEntity>
     * @return
     */
    public <OtherEntity> LambdaGenericJoinWrapper<MainEntity> leftJoin(Class<OtherEntity> otherEntityClass, Pair<FieldFunction<MainEntity, ?>, FieldFunction<OtherEntity, ?>>... onEqConditionPairs) {
        return leftJoin(getEntityClass(), otherEntityClass, onEqConditionPairs);
    }

    /**
     * 【任意实体类型】与【任意实体类型】进行 (Left Join) 关联,同时可以指定【多个EQ】条件的方法
     * <p>
     * SQL示例:
     * select * from OtherEntity1 o1 left join OtherEntity2 o2 on o1.ok1 = o2.ok1  and  o1.ok2 = o2.ok2...
     *
     * @param o1Class
     * @param o2Class
     * @param onEqConditionPairs
     * @param <OtherEntity1>
     * @param <OtherEntity2>
     * @return
     */
    public <OtherEntity1, OtherEntity2> LambdaGenericJoinWrapper<MainEntity> leftJoin(Class<OtherEntity1> o1Class, Class<OtherEntity2> o2Class, Pair<FieldFunction<OtherEntity1, ?>, FieldFunction<OtherEntity2, ?>>... onEqConditionPairs) {
        return leftJoin(o1Class, o2Class, getOnConditionWrapperByConditionPairs(onEqConditionPairs));
    }

    /**
     * 【主实体类型】与【任意实体类型】进行 (Left Join) 关联,同时可以指定【复杂】条件的方法
     * <p>
     * SQL示例:
     * select * from MainEntity m left join OtherEntity o on m.ok1 = o.ok1  and  m.ok2 in (1,2,3,4,5,6) ...
     *
     * @param otherEntityClass   任何Wrapper对象(仅用于获取该实体的表名和别名)
     * @param onConditionWrapper 复杂On条件组装项
     * @param <OtherEntity>      任意实体
     * @return
     */
    public <OtherEntity> LambdaGenericJoinWrapper<MainEntity> leftJoin(Class<OtherEntity> otherEntityClass, LambdaOnConditionWrapper onConditionWrapper) {
        return leftJoin(getEntityClass(), otherEntityClass, onConditionWrapper);
    }

    /**
     * 【任意实体类型】与【任意实体类型】进行 (Left Join) 关联,同时可以指定【复杂】条件的方法
     * <p>
     * SQL示例:
     * select * from OtherEntity1 o1 left join OtherEntity2 o2 on o1.ok1 != o2.ok1  and  o1.ok2 in (1,2,3,4,5,6) ...
     *
     * @param o1Class
     * @param o2Class
     * @param onConditionWrapper On条件写入对象
     * @param <OtherEntity1>
     * @param <OtherEntity2>
     * @return
     */
    public <OtherEntity1, OtherEntity2> LambdaGenericJoinWrapper<MainEntity> leftJoin(Class<OtherEntity1> o1Class, Class<OtherEntity2> o2Class, LambdaOnConditionWrapper onConditionWrapper) {
        return join(GenericJoinTypeEnum.LEFT_JOIN, o1Class, o2Class, onConditionWrapper);
    }

    /**
     * 【主实体类型Wrapper】与【任意实体类型Wrapper】进行 (Left Join) 关联,同时可以指定【复杂】条件的方法
     * <p>
     * SQL示例:
     * select * from MainEntity m left join OtherEntity o on m.ok1 = o.ok1  and  m.ok2 in (1,2,3,4,5,6) ...
     *
     * @param otherEntityWrapper 任何Wrapper对象(仅用于获取该实体的表名和别名)
     * @param onConditionWrapper 复杂On条件组装项
     * @param <OtherEntity>      任意实体
     * @return
     */
    public <OtherEntity> LambdaGenericJoinWrapper<MainEntity> leftJoin(AbstractWrapper<OtherEntity, ?> otherEntityWrapper, LambdaOnConditionWrapper onConditionWrapper) {
        return leftJoin(this, otherEntityWrapper, onConditionWrapper);
    }

    /**
     * 【任意实体类型Wrapper】与【任意实体类型Wrapper】进行 (Left Join) 关联,同时可以指定【复杂】条件的方法
     * <p>
     * SQL示例:
     * select * from OtherEntity1 o1 left join OtherEntity2 o2 on o1.ok1 = o2.ok1  and  o1.ok2 in (1,2,3,4,5,6) ...
     *
     * @param o1Wrapper          任何对象,仅用于获取实体对应的表名数据
     * @param o2Wrapper          任何对象,仅用于获取实体对应的表名数据
     * @param onConditionWrapper On条件写入对象
     * @param <OtherEntity1>
     * @param <OtherEntity2>
     * @return
     */
    public <OtherEntity1, OtherEntity2> LambdaGenericJoinWrapper<MainEntity> leftJoin(AbstractWrapper<OtherEntity1, ?> o1Wrapper, AbstractWrapper<OtherEntity2, ?> o2Wrapper, LambdaOnConditionWrapper onConditionWrapper) {
        return join(GenericJoinTypeEnum.LEFT_JOIN, o1Wrapper, o2Wrapper, onConditionWrapper);
    }

    /**
     * 【主实体类型】与【任意实体类型】进行 (Inner Join) 关联,同时可以指定【单个EQ】条件的方法
     * <p>
     * SQL示例:
     * select * from MainEntity m Inner Join OtherEntity o on m.mainOnEqKey = o.otherOnEqKey
     *
     * @param otherEntityClass 任意实体类型
     * @param mainOnEqKey      主实体类型属性
     * @param otherOnEqKey     任意实体类型属性
     * @param <OtherEntity>    任意实体对象
     * @return
     */
    public <OtherEntity> LambdaGenericJoinWrapper<MainEntity> innerJoin(Class<OtherEntity> otherEntityClass, FieldFunction<MainEntity, ?> mainOnEqKey, FieldFunction<OtherEntity, ?> otherOnEqKey) {
        return innerJoin(getEntityClass(), otherEntityClass, mainOnEqKey, otherOnEqKey);
    }

    /**
     * 【任意实体类型】与【任意实体类型】进行 (Inner Join) 关联,同时可以指定【单个EQ】条件的方法
     * <p>
     * SQL示例:
     * select * from OtherEntity1 o1 Inner Join OtherEntity2 o2 on o1.o1OnEqKey = o2.o2OnEqKey
     *
     * @param o1Class
     * @param o2Class
     * @param o1OnEqKey
     * @param o2OnEqKey
     * @param <OtherEntity1> 任意实体类型
     * @param <OtherEntity2> 任意实体类型
     * @return
     */
    public <OtherEntity1, OtherEntity2> LambdaGenericJoinWrapper<MainEntity> innerJoin(Class<OtherEntity1> o1Class, Class<OtherEntity2> o2Class, FieldFunction<OtherEntity1, ?> o1OnEqKey, FieldFunction<OtherEntity2, ?> o2OnEqKey) {
        return innerJoin(o1Class, o2Class, new Pair<>(o1OnEqKey, o2OnEqKey));
    }

    /**
     * 【主实体类型】与【任意实体类型】进行 (Inner Join) 关联,同时可以指定【多个EQ】条件的方法
     * <p>
     * SQL示例:
     * select * from MainEntity m Inner Join OtherEntity o on m.ok1 = o.ok1  and  m.ok2 = o.ok2 ...
     *
     * @param otherEntityClass
     * @param onEqConditionPairs
     * @param <OtherEntity>
     * @return
     */
    public <OtherEntity> LambdaGenericJoinWrapper<MainEntity> innerJoin(Class<OtherEntity> otherEntityClass, Pair<FieldFunction<MainEntity, ?>, FieldFunction<OtherEntity, ?>>... onEqConditionPairs) {
        return innerJoin(getEntityClass(), otherEntityClass, onEqConditionPairs);
    }

    /**
     * 【任意实体类型】与【任意实体类型】进行 (Inner Join) 关联,同时可以指定【多个EQ】条件的方法
     * <p>
     * SQL示例:
     * select * from OtherEntity1 o1 Inner Join OtherEntity2 o2 on o1.ok1 = o2.ok1  and  o1.ok2 = o2.ok2...
     *
     * @param o1Class
     * @param o2Class
     * @param onEqConditionPairs
     * @param <OtherEntity1>
     * @param <OtherEntity2>
     * @return
     */
    public <OtherEntity1, OtherEntity2> LambdaGenericJoinWrapper<MainEntity> innerJoin(Class<OtherEntity1> o1Class, Class<OtherEntity2> o2Class, Pair<FieldFunction<OtherEntity1, ?>, FieldFunction<OtherEntity2, ?>>... onEqConditionPairs) {
        return innerJoin(o1Class, o2Class, getOnConditionWrapperByConditionPairs(onEqConditionPairs));
    }

    /**
     * 【主实体类型】与【任意实体类型】进行 (Inner Join) 关联,同时可以指定【复杂】条件的方法
     * <p>
     * SQL示例:
     * select * from MainEntity m Inner join OtherEntity o on m.ok1 = o.ok1  and  m.ok2 in (1,2,3,4,5,6) ...
     *
     * @param otherEntityClass   任何Wrapper对象(仅用于获取该实体的表名和别名)
     * @param onConditionWrapper 复杂On条件组装项
     * @param <OtherEntity>      任意实体
     * @return
     */
    public <OtherEntity> LambdaGenericJoinWrapper<MainEntity> innerJoin(Class<OtherEntity> otherEntityClass, LambdaOnConditionWrapper onConditionWrapper) {
        return innerJoin(getEntityClass(), otherEntityClass, onConditionWrapper);
    }

    /**
     * 【任意实体类型】与【任意实体类型】进行 (Inner Join) 关联,同时可以指定【复杂】条件的方法
     * <p>
     * SQL示例:
     * select * from OtherEntity1 o1 Inner Join OtherEntity2 o2 on o1.ok1 != o2.ok1  and  o1.ok2 in (1,2,3,4,5,6) ...
     *
     * @param o1Class
     * @param o2Class
     * @param onConditionWrapper On条件写入对象
     * @param <OtherEntity1>
     * @param <OtherEntity2>
     * @return
     */
    public <OtherEntity1, OtherEntity2> LambdaGenericJoinWrapper<MainEntity> innerJoin(Class<OtherEntity1> o1Class, Class<OtherEntity2> o2Class, LambdaOnConditionWrapper onConditionWrapper) {
        return join(GenericJoinTypeEnum.INNER_JOIN, o1Class, o2Class, onConditionWrapper);
    }

    /**
     * 【主实体类型Wrapper】与【任意实体类型Wrapper】进行 (Inner Join) 关联,同时可以指定【复杂】条件的方法
     * <p>
     * SQL示例:
     * select * from MainEntity m Inner Join OtherEntity o on m.ok1 = o.ok1  and  m.ok2 in (1,2,3,4,5,6) ...
     *
     * @param otherEntityWrapper 任何Wrapper对象(仅用于获取该实体的表名和别名)
     * @param onConditionWrapper 复杂On条件组装项
     * @param <OtherEntity>      任意实体
     * @return
     */
    public <OtherEntity> LambdaGenericJoinWrapper<MainEntity> innerJoin(AbstractWrapper<OtherEntity, ?> otherEntityWrapper, LambdaOnConditionWrapper onConditionWrapper) {
        return innerJoin(this, otherEntityWrapper, onConditionWrapper);
    }

    /**
     * 【任意实体类型Wrapper】与【任意实体类型Wrapper】进行 (Inner Join) 关联,同时可以指定【复杂】条件的方法
     * <p>
     * SQL示例:
     * select * from OtherEntity1 o1 Inner Join OtherEntity2 o2 on o1.ok1 = o2.ok1  and  o1.ok2 in (1,2,3,4,5,6) ...
     *
     * @param o1Wrapper          任何对象,仅用于获取实体对应的表名数据
     * @param o2Wrapper          任何对象,仅用于获取实体对应的表名数据
     * @param onConditionWrapper On条件写入对象
     * @param <OtherEntity1>
     * @param <OtherEntity2>
     * @return
     */
    public <OtherEntity1, OtherEntity2> LambdaGenericJoinWrapper<MainEntity> innerJoin(AbstractWrapper<OtherEntity1, ?> o1Wrapper, AbstractWrapper<OtherEntity2, ?> o2Wrapper, LambdaOnConditionWrapper onConditionWrapper) {
        return join(GenericJoinTypeEnum.INNER_JOIN, o1Wrapper, o2Wrapper, onConditionWrapper);
    }

//    public <OtherEntity> LambdaJoinWrapper<MainEntity> rightJoin(LambdaQueryWrapper<OtherEntity> otherQueryWrapper, FieldFunction<MainEntity, ?> mainEntityOnKey, FieldFunction<OtherEntity, ?> otherEntityOnKey) {
//        return rightJoin(otherQueryWrapper, new Pair<>(mainEntityOnKey, otherEntityOnKey));
//    }
//
//    /**
//     * RIGHT JOIN 通用方法
//     *
//     * @param otherQueryWrapper
//     * @param onConditionPairs
//     * @param <OtherEntity>
//     * @return
//     */
//    public <OtherEntity> LambdaJoinWrapper<MainEntity> rightJoin(LambdaQueryWrapper<OtherEntity> otherQueryWrapper, Pair<FieldFunction<MainEntity, ?>, FieldFunction<OtherEntity, ?>>... onConditionPairs) {
//        return join(JoinTypeEnum.RIGHT_JOIN, otherQueryWrapper, onConditionPairs);
//    }
//
//    /**
//     * 并集查询（聚合数据会去重）
//     *
//     * @param otherQueryWrapper
//     * @param <OtherEntity>
//     * @return
//     */
//    public <OtherEntity> LambdaJoinWrapper<MainEntity> union(LambdaQueryWrapper<OtherEntity> otherQueryWrapper) {
//        return join(JoinTypeEnum.UNION_JOIN, otherQueryWrapper);
//    }
//
//    /**
//     * 并集查询（聚合数据不会去重）
//     *
//     * @param otherQueryWrapper
//     * @param <OtherEntity>
//     * @return
//     */
//    public <OtherEntity> LambdaJoinWrapper<MainEntity> unionAll(LambdaQueryWrapper<OtherEntity> otherQueryWrapper) {
//        return join(JoinTypeEnum.UNION_ALL_JOIN, otherQueryWrapper);
//    }

    /**
     * 任意实体类型与任意实体类型进行  Join 关联条件,同时可以指定任意条件系列
     * 本方法等同 OtherEntity1 o1 left join OtherEntity2 o2 on o1.ok1 != o2.ok1  and  o1.ok2 in (1,2,3,4,5,6) ...
     *
     * @param joinType           关联类型
     * @param o1Class
     * @param o2Class
     * @param onConditionWrapper On条件写入对象
     * @param <OtherEntity1>
     * @param <OtherEntity2>
     * @return
     */
    public <OtherEntity1, OtherEntity2> LambdaGenericJoinWrapper<MainEntity> join(GenericJoinTypeEnum joinType, Class<OtherEntity1> o1Class, Class<OtherEntity2> o2Class, LambdaOnConditionWrapper onConditionWrapper) {
        AbstractWrapper o1Wrapper = o1Class == null ? null : o1Class.equals(getEntityClass()) ? this : Wrappers.queryWrapper(o1Class),
                o2Wrapper = o2Class == null ? null : o2Class.equals(getEntityClass()) ? this : Wrappers.queryWrapper(o2Class);
        return join(joinType, o1Wrapper, o2Wrapper, onConditionWrapper);
    }

    /**
     * 任意Wrapper对应的任意实体类型与任意Wrapper对应的任意实体类型进行  Join 关联条件,同时可以指定任意条件系列
     * 本方法等同 OtherEntity1 o1 left join OtherEntity2 o2 on o1.ok1 = o2.ok1  and  o1.ok2 in (1,2,3,4,5,6) ...
     * <p>
     * 备注:
     * 1.此方法具备指定Join多个相同的实体类型的能力,通常在分区表中体现.
     * 例: 分区表=(part_[num],part_[num]),此处需要将num设置在 {@link AbstractWrapper#setTableSuffix(String)}中,即能开启多个相同实体的Join
     * <p>
     *
     * @param joinType           关联类型
     * @param o1Wrapper          任何对象,仅用于获取实体对应的表名数据
     * @param o2Wrapper          任何对象,仅用于获取实体对应的表名数据
     * @param onConditionWrapper On条件写入对象
     * @param <OtherEntity1>
     * @param <OtherEntity2>
     * @return
     */
    public <OtherEntity1, OtherEntity2> LambdaGenericJoinWrapper<MainEntity> join(GenericJoinTypeEnum joinType, AbstractWrapper<OtherEntity1, ?> o1Wrapper, AbstractWrapper<OtherEntity2, ?> o2Wrapper, LambdaOnConditionWrapper onConditionWrapper) {
        return addJoinSegment(joinType, o1Wrapper, o2Wrapper, onConditionWrapper);
    }

    /**
     * 添加Join关联条件
     * 注意:
     * 1.不能重置设置两张相同的表对象,否则会取最后设置的一条数据.
     *
     * @param joinType
     * @param o1Wrapper          左方关联实体Wrapper,不能为空
     * @param o2Wrapper          右方关联实体Wrapper,不能为空
     * @param onConditionWrapper
     * @param <OtherEntity1>
     * @param <OtherEntity2>
     * @return
     */
    protected <OtherEntity1, OtherEntity2> LambdaGenericJoinWrapper<MainEntity> addJoinSegment(GenericJoinTypeEnum joinType, AbstractWrapper<OtherEntity1, ?> o1Wrapper, AbstractWrapper<OtherEntity2, ?> o2Wrapper, LambdaOnConditionWrapper onConditionWrapper) {
        if (joinType == null) {
            throw new LambdaIllegalParamException("使用Join语句语法时,[joinType(连接类型)]必传!");
        }
        if (o1Wrapper == null || (o1Wrapper.getEntityClass()) == null) {
            throw new LambdaIllegalParamException("使用Join语句语法=[" + joinType.getKeyWord() + "]时,不存在连接的左部Wrapper或实体类型!");
        }
        if (o2Wrapper == null || (o2Wrapper.getEntityClass()) == null) {
            throw new LambdaIllegalParamException("使用Join语句语法=[" + joinType.getKeyWord() + "]时,不存在连接的右部Wrapper或实体类型!");
        }
        JoinSegment<OtherEntity1, OtherEntity2> joinSegment = new JoinSegment<>();
        joinSegment.setJoinType(joinType);
        joinSegment.setLeftJoinWrapper(o1Wrapper);
        joinSegment.setRightJoinWrapper(o2Wrapper);

        joinSegment = replaceOrAddSegment(joinSegment, SegmentEnum.JOIN, (Field) null, null);

        //多表数据下需要提前框定实体别名.
        //add by lx Date:2023/2/27 Desc:如为this,则无需现在生成.
        if (o1Wrapper != this) {
            this.setTableAlias(o1Wrapper.getEntityClass(), o1Wrapper.getTableAliasName(false, o1Wrapper.getEntityClass()));
        }
        if (o2Wrapper != this) {
            this.setTableAlias(o2Wrapper.getEntityClass(), o2Wrapper.getTableAliasName(false, o2Wrapper.getEntityClass()));
        }
        //设置On连接查询条件Wrapper
        joinSegment.setOnConditionWrapper(onConditionWrapper);
        return this;
    }

    /**
     * 增加通用列名语句
     * 场景:
     * 1.增加Select 普通列
     * 2.新增或替换Select 函数聚合列
     *
     * @param aliasName     聚合列别名
     * @param childWrapper  子查询项
     * @param fnn
     * @param keyWorldEnum
     * @param <OtherEntity> 任意实体
     * @return
     */
    protected <OtherEntity> LambdaGenericJoinWrapper<MainEntity> addColumnSegment(String aliasName, AbstractCommonConditionWrapper childWrapper, ColumnKeyWorldEnum keyWorldEnum, FieldFunction<OtherEntity, ?>... fnn) {
        if (ArrayUtil.isEmpty(fnn)) {
            return this;
        }
        //TODO 当前仅支持单个聚合语句写入.
        if (fnn.length > 1) {
            throw new LambdaIllegalParamException("当前仅支持单个聚合语句写入,请等待下次计划开发!");
        }
        FieldFunction<OtherEntity, ?> firstFieldFunction = fnn[0];

        ColumnSegment dc = replaceOrAddSegment(new ColumnSegment(), SegmentEnum.COLUMN, firstFieldFunction, null);
        dc.setChildConditionWrapper(childWrapper);
        dc.setAliasName(aliasName);

        if (keyWorldEnum != null) {
            //设置列扩展属性列表
            dc.getColumnExtendList().add(keyWorldEnum);
        }
        return this;
    }

    @Override
    protected void setHibernateParamByQuery0(boolean isHQL, Query query) {
        //其他映射
        Map<SegmentEnum, List<Segment>> segmentsMap = getSegmentsByEnums(SegmentEnum.COLUMN, SegmentEnum.WHERE, SegmentEnum.LIMIT, SegmentEnum.JOIN);
        segmentsMap.forEach((e1, l1) -> {
            if (CollectionUtil.isEmpty(l1)) {
                return;
            }
            for (Segment sn : l1) {
                sn.setHibernateParamByQuery(isHQL, query);
            }
        });
    }

    @Override
    protected void setCompleteQL0(boolean isHQL, String qlString) {
        Class<MainEntity> entityClass = getEntityClass();
        //用于映射后续的列名对象和数据封装. 如存在统一替代符号【*】,则必须指定实体类
        int index;
        {
            //大小写问题处理.
            String upQlString = qlString.toUpperCase();
            if (!upQlString.startsWith(SqlKeyWordConstant.SELECT) || (index = upQlString.indexOf(SqlKeyWordConstant.FROM)) == -1) {
                throw new LambdaCheckException("查询Wrapper下对应的语句必须为查询语句!");
            }
        }
        //解析属性相关数据
        String[] columnChildArray = qlString.substring(SqlKeyWordConstant.SELECT.length(), index).split(CommonConstant.COMMA);

        if (columnChildArray.length == 1 && columnChildArray[0].contains(CommonConstant.ASTERISK)) {
            //判断是否存在*号且只有一个解析字段.
            if (entityClass == null) {
                throw new LambdaCheckException("当查询语句中为不可变变量[*]时,实体类对象必须存在!");
            }
            //解析*符号
            List<Field> fields = explainColumnFieldListByEntityClass();
            for (Field field : fields) {
                createAndAddSegment(new ColumnSegment(), SegmentEnum.COLUMN, field, null);
            }
        }

        //解析单独构建的列名项
        for (String columnChild : columnChildArray) {
            //组成结构：列名 + 列别名(可能不存在)
            String[] columnNameAndAliasArr = columnChild.trim().split("( AS )|( as )|( aS )|( As )|[ ]");
            ColumnSegment tem = createAndAddSegment(new ColumnSegment(), SegmentEnum.COLUMN, (Field) null, columnNameAndAliasArr[0]);
            if (columnNameAndAliasArr.length > 1) {
                tem.setAliasName(columnNameAndAliasArr[1]);
            }
        }
    }

    @Override
    protected String getCompleteQL0(boolean isHQL, AbstractWrapper parentWrapper) {
        StringBuilder sqlBuilder = new StringBuilder(512);
        //1.检查和构建查询列.
        if (!existDataFromSegmentEnum(SegmentEnum.COLUMN)) {
            //如不存在,则需要根据[EntityClass]推断所有列名
            List<Field> fields = explainColumnFieldListByEntityClass();
            for (Field field : fields) {
                createAndAddSegment(new ColumnSegment(), SegmentEnum.COLUMN, field, null);
            }
        }
        sqlBuilder.append(buildConditions(isHQL, parentWrapper, SegmentEnum.COLUMN));
        //2.构建表.
        sqlBuilder.append(SqlKeyWordConstant.FROM);
        //相关表项由Join指定生成
        sqlBuilder.append(String.format(SqlFormatConstant.AS_FORMAT, inferAndGetTableName(isHQL), getTableAliasName(false)));
        //3.构建Join项
        sqlBuilder.append(buildConditions(isHQL, parentWrapper, SegmentEnum.JOIN));
        //4.构建条件项.
        sqlBuilder.append(buildConditions(isHQL, parentWrapper, SegmentEnum.WHERE));
        //5.构建分组项.
        sqlBuilder.append(buildConditions(isHQL, parentWrapper, SegmentEnum.GROUP_BY));
        //6.构建分组条件
        sqlBuilder.append(buildConditions(isHQL, parentWrapper, SegmentEnum.HAVING));
        //7.构建排序条件
        sqlBuilder.append(buildConditions(isHQL, parentWrapper, SegmentEnum.ORDER_BY));
        //8.构建分页条件
        sqlBuilder.append(buildConditions(isHQL, parentWrapper, SegmentEnum.LIMIT));
        return sqlBuilder.toString();
    }

    @Override
    public <Response> Response convertToResponse(Class<Response> resultClass, Object hibernateRes) {
        return resultConvertProxy.convertToResponse(resultClass, hibernateRes);
    }

    @Override
    public <Response> Response convertToResponse(Response response, Object hibernateRes) {
        return resultConvertProxy.convertToResponse(response, hibernateRes);
    }

    @Override
    public <Response> List<Response> convertToResponseList(List<Object> hibernateResList, Class<Response> resultClass) {
        return resultConvertProxy.convertToResponseList(hibernateResList, resultClass);
    }

    private <OtherEntity1, OtherEntity2> LambdaOnConditionWrapper getOnConditionWrapperByConditionPairs(Pair<FieldFunction<OtherEntity1, ?>, FieldFunction<OtherEntity2, ?>>... onEqConditionPairs) {
        LambdaOnConditionWrapper onConditionWrapper = null;
        if (ArrayUtil.isNotEmpty(onEqConditionPairs)) {
            onConditionWrapper = getOnConditionWrapper();
            //封装OnConditionWrapper,设置所有条件=EQ
            for (Pair<FieldFunction<OtherEntity1, ?>, FieldFunction<OtherEntity2, ?>> onEqConditionPair : onEqConditionPairs) {
                onConditionWrapper.eq(onEqConditionPair.getKey(), onEqConditionPair.getValue());
            }
        }
        return onConditionWrapper;
    }
}
